package top.wyloop.intoeins.module.ledger.controller;

import cn.dev33.satoken.annotation.SaCheckLogin;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.dev33.satoken.stp.StpUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import top.wyloop.intoeins.exception.SystemException;
import top.wyloop.intoeins.module.ledger.model.consts.AuthorityConst;
import top.wyloop.intoeins.module.ledger.model.consts.InitAccountConst;
import top.wyloop.intoeins.module.ledger.model.entity.Account;
import top.wyloop.intoeins.module.ledger.model.form.AccountForm;
import top.wyloop.intoeins.module.ledger.service.AccountService;
import top.wyloop.intoeins.response.Response;

import java.util.List;

/**
 * @author Wyatt6
 * @date 2025/3/28
 */
@Slf4j
@RestController
@RequestMapping("/api/ledger/account")
public class AccountController {
    @Autowired
    private AccountService accountService;

    /**
     * 添加记账账户
     *
     * @param input 新记账账户数据
     * @return {account 新记账账户对象}
     */
    @SaCheckLogin
    @SaCheckPermission(AuthorityConst.ACCOUNT_ADD)
    @PostMapping("/addAccount")
    @Transactional(isolation = Isolation.SERIALIZABLE)
    public Response addAccount(@RequestBody AccountForm input) {
        log.info("[[新增记账账户]]");
        Assert.notNull(input, "新记账账户信息为空");
        Assert.hasText(input.getName(), "记账账户名称为空");
        log.info("请求参数: {}", input);

        Long userId = StpUtil.getLoginIdAsLong();
        Account account = accountService.createAccount(userId, input.convert());
        return new Response().success().addData("account", account);
    }

    /**
     * 删除记账账户
     *
     * @param accountId 要删除的记账账户ID
     */
    @SaCheckLogin
    @SaCheckPermission(AuthorityConst.ACCOUNT_DELETE)
    @GetMapping("/deleteAccount")
    @Transactional(isolation = Isolation.SERIALIZABLE)
    public Response deleteAccount(@RequestParam("accountId") Long accountId) {
        log.info("[[删除记账账户]]");
        Assert.notNull(accountId, "记账账户ID为空");
        log.info("请求参数：accountId=[{}]", accountId);

        Long userId = StpUtil.getLoginIdAsLong();
        accountService.deleteAccount(userId, accountId);
        return new Response().success();
    }

    /**
     * 编辑记账账户
     *
     * @param input 新记账账户数据
     * @return {account 新记账账户对象}
     */
    @SaCheckLogin
    @SaCheckPermission(AuthorityConst.ACCOUNT_EDIT)
    @PostMapping("/editAccount")
    public Response editAccount(@RequestBody AccountForm input) {
        log.info("[[编辑记账账户]]");
        Assert.notNull(input, "输入数据为空");
        Assert.notNull(input.getId(), "记账账户ID为空");
        log.info("请求参数：{}", input);

        Long userId = StpUtil.getLoginIdAsLong();
        Account account = accountService.updateAccount(userId, input.convert());
        return new Response().success().addData("account", account);
    }

    /**
     * 交换两个记账账户位置
     *
     * @param id1 记账账户1的ID
     * @param id2 记账账户2的ID
     * @return {account1 新记账账户1, account2 新记账账户2}
     */
    @SaCheckLogin
    @SaCheckPermission(AuthorityConst.ACCOUNT_EDIT)
    @GetMapping("/swapPosition")
    public Response swapPosition(@RequestParam("id1") Long id1, @RequestParam("id2") Long id2) {
        log.info("[[交换两个记账账户位置]]");
        Assert.notNull(id1, "id1为空");
        Assert.notNull(id2, "id2为空");
        log.info("请求参数: id1=[{}], id2=[{}]", id1, id2);

        log.info("获取两个记账账户数据");
        Long userId = StpUtil.getLoginIdAsLong();
        Account account1 = accountService.findAccountById(userId, id1);
        Account account2 = accountService.findAccountById(userId, id2);
        if (account1 != null && account2 != null) {
            log.info("(id1, sortId1)=({}, {})", id1, account1.getSortId());
            log.info("(id2, sortId2)=({}, {})", id2, account2.getSortId());

            // 自动生成的<默认虚拟记账账户>记账账户不支持
            if (account1.getName().equals(InitAccountConst.AUTO_GEN_NAME) || account2.getName().equals(InitAccountConst.AUTO_GEN_NAME)) {
                throw new SystemException("无法改变" + InitAccountConst.AUTO_GEN_NAME + "记账账户位置");
            }

            log.info("交换sortId");
            Long tempSortId = account1.getSortId();
            account1.setSortId(account2.getSortId());
            account2.setSortId(tempSortId);

            Account newAccount1 = accountService.updateAccount(userId, account1);
            Account newAccount2 = accountService.updateAccount(userId, account2);
            log.info("交换sortId完成");

            return new Response().success()
                    .addData("account1", newAccount1)
                    .addData("account2", newAccount2);
        } else {
            throw new SystemException("无法找到记账账户数据");
        }
    }

    /**
     * 获取记账账户列表
     *
     * @return {accounts 记账账户列表}
     */
    @SaCheckLogin
    @SaCheckPermission(AuthorityConst.ACCOUNT_QUERY)
    @GetMapping("/getAccounts")
    public Response getAccounts() {
        log.info("[[获取记账账户列表]]");
        Long userId = StpUtil.getLoginIdAsLong();
        List<Account> accounts = accountService.getAccounts(userId);
        return new Response().success().addData("accounts", accounts);
    }
}
